﻿using System;
using System.Linq;
using System.Transactions;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetNuke.Entities.Users;
using DotNetNuke.Modules._2DoTasks.Components;
using DotNetNuke.Modules._2DoTasks.Components.Controllers;
using DotNetNuke.Modules._2DoTasks.Components.Entities;
using DotNetNuke.Modules._2DoTasks.Components.ExceptionHandling;
using DotNetNuke.Security.Roles;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;

namespace DotNetNuke.Modules._2DoTasks
{
    public partial class ProjectMembers : _2DoTasksModuleBase
    {
        #region "Properties"

        /// <summary>
        /// returns the role to collect members from
        /// </summary>
        private string MembersRole
        {
            get
            {
                return (this.Parent as Project).MemberRole;
            }
        }

        /// <summary>
        /// property for the current user, when editing a project if it's a manager or not
        /// </summary>
        private bool IsManager
        {
            get
            {
                return (this.Parent as Project).IsManager;
            }
        }

        private Nullable<int> CurrentUserId
        {
            get
            {
                if (ViewState["ProjectMembers_CurrentUserId"] != null)
                    return Convert.ToInt32(ViewState["ProjectMembers_CurrentUserId"]);
                return null;
            }
            set
            {
                ViewState["ProjectMembers_CurrentUserId"] = value;
            }
        }

        #endregion "Properties"

        #region "Events"

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                Messages.ClearMessages();

                FillLanguages();

                //Implement your edit logic for your module
                if (!Page.IsPostBack)
                {
                    int ownerId = UserId;

                    FillControls();
                    if (ProjectId.HasValue)
                    {
                        BindProjectMembers(ProjectId.Value, out ownerId);
                    }

                    //remove the project owner
                    RemoveOwner(ownerId);
                }
            }
            catch (Exception exc) //Module failed to load
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }

        /// <summary>
        /// removes the project owner from the list of members
        /// </summary>
        private void RemoveOwner(int ownerId)
        {
            ListItem item = drp_members.Items.OfType<ListItem>().Where(p => p.Value == ownerId.ToString()).FirstOrDefault();
            if (item != null)
                drp_members.Items.Remove(item);
        }

        /// <summary>
        /// Adds a project member
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btn_addMember_Click(object sender, EventArgs e)
        {
            try
            {
                using (UnitOfWork uof = new UnitOfWork(PortalId, ModuleId))
                {
                    int userId;
                    if (MemberParametersCorrectlyFilled(out userId))
                    {
                        ProjectMemberController ProjectMemberController = new ProjectMemberController(uof, ProjectId.Value);

                        using (TransactionScope scope = new TransactionScope())
                        {
                            _ProjectMember projectMember = new _ProjectMember
                            {
                                IsManager = chk_isManager.Checked,
                                ProjectId = ProjectId.Value,
                                UserId = userId
                            };

                            ProjectMemberController.Add(projectMember);
                            scope.Complete();
                        }

                        Messages.ShowSuccess(Localization.GetString("AddSuccess", this.LocalResourceFile));

                        ClearProjectMemberControl();
                        FillProjectMembers(uof, ProjectMemberController);
                    }
                }
            }
            catch (ProjectMemberValidationException exc)
            {
                ProjectMemberController.InsertStatus status =
                    (ProjectMemberController.InsertStatus)Enum.Parse(typeof(ProjectMemberController.InsertStatus), exc.ErrorCode().ToString());

                switch (status)
                {
                    case ProjectMemberController.InsertStatus.ProjectNotFound:
                        Messages.ShowWarning(Localization.GetString("WarningProjectNotFound", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.InsertStatus.UserAlreadyAMember:
                        Messages.ShowWarning(Localization.GetString("WarningUserAlreadyAMember", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.InsertStatus.NOTMANAGER:
                        Messages.ShowWarning(Localization.GetString("WarningNOTMANAGER", this.LocalResourceFile));
                        break;

                    default:
                        Exceptions.LogException(exc);
                        Messages.ShowError(Localization.GetString("ErrorAddMember", this.LocalResourceFile));
                        break;
                }
            }
            catch (Exception exc)
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }

        protected void lst_projectMembers_LayoutCreated(object sender, EventArgs e)
        {
            (lst_projectMembers.FindControl("lt_username") as Literal).Text = Localization.GetString("TitleUserName", this.LocalResourceFile);
            (lst_projectMembers.FindControl("lt_IsManager") as Literal).Text = Localization.GetString("TitleIsManager", this.LocalResourceFile);
        }

        protected void lst_projectMembers_ItemDataBound(object sender, System.Web.UI.WebControls.ListViewItemEventArgs e)
        {
            if (e.Item.ItemType == ListViewItemType.DataItem)
            {
                var lnk_edit = e.Item.FindControl("lnk_edit") as LinkButton;
                var lnk_delete = e.Item.FindControl("lnk_delete") as LinkButton;
                var chk_isManagerLst = e.Item.FindControl("chk_isManagerLst") as CheckBox;

                if (IsManager)
                {
                    var curTask = (_ProjectMember)e.Item.DataItem;

                    if (lnk_edit != null && lnk_delete != null)
                    {
                        lnk_edit.CommandArgument = curTask.UserId.ToString();
                        lnk_delete.CommandArgument = curTask.UserId.ToString();

                        DotNetNuke.UI.Utilities.ClientAPI.AddButtonConfirm(lnk_delete, Localization.GetString("DeleteConfirm", this.LocalResourceFile));
                    }
                }
                else
                {
                    lnk_edit.Enabled = lnk_delete.Enabled = chk_isManagerLst.Enabled = IsManager;
                }
            }
        }

        /// <summary>
        /// Prepares for the edition of a project member
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void lnkSave_Click(object sender, EventArgs e)
        {
            try
            {
                using (UnitOfWork uof = new UnitOfWork(PortalId, ModuleId))
                {
                    ProjectMemberController projectMemberController = new ProjectMemberController(uof, ProjectId.Value);
                    _ProjectMember projectMember = projectMemberController.Get(Convert.ToInt32((sender as LinkButton).CommandArgument));
                    bool isManager = ((sender as LinkButton).Parent.FindControl("chk_isManagerLst") as CheckBox).Checked;

                    if (projectMember.IsManager != isManager)
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
                            projectMember.IsManager = isManager;
                            projectMemberController.Update(projectMember);
                            scope.Complete();
                        }
                        Messages.ShowSuccess(Localization.GetString("UpdateSuccess", this.LocalResourceFile));
                    }
                }
            }
            catch (ProjectMemberValidationException exc)
            {
                ProjectMemberController.UpdateStatus status =
                    (ProjectMemberController.UpdateStatus)Enum.Parse(typeof(ProjectMemberController.UpdateStatus), exc.ErrorCode().ToString());

                switch (status)
                {
                    case ProjectMemberController.UpdateStatus.ProjectNotFound:
                        Messages.ShowWarning(Localization.GetString("WarningProjectNotFound", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.UpdateStatus.CannotChangeOwner:
                        Messages.ShowWarning(Localization.GetString("WarningCannotChangeOwner", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.UpdateStatus.NOTMANAGER:
                        Messages.ShowWarning(Localization.GetString("WarningNOTMANAGER", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.UpdateStatus.CANNOTCHANGEUSER:
                        Messages.ShowWarning(Localization.GetString("WarningCANNOTCHANGEUSER", this.LocalResourceFile));
                        break;

                    default:
                        Exceptions.LogException(exc);
                        Messages.ShowError(Localization.GetString("ErrorUpdateMember", this.LocalResourceFile));
                        break;
                }
            }
            catch (Exception exc)
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }

        /// <summary>
        /// Deletes the passed task time entry
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void lnkDelete_Click(object sender, EventArgs e)
        {
            try
            {
                using (UnitOfWork uof = new UnitOfWork(PortalId, ModuleId))
                {
                    ProjectMemberController ProjectMemberController = new ProjectMemberController(uof, ProjectId.Value);
                    _ProjectMember projectMember = new _ProjectMember { UserId = Convert.ToInt32((sender as LinkButton).CommandArgument), ProjectId = ProjectId.Value };
                    using (TransactionScope scope = new TransactionScope())
                    {
                        ProjectMemberController.Delete(projectMember);
                        scope.Complete();
                    }
                    FillProjectMembers(uof, ProjectMemberController);
                    Messages.ShowSuccess(Localization.GetString("DeleteSuccess", this.LocalResourceFile));
                }
            }
            catch (ProjectMemberValidationException exc)
            {
                ProjectMemberController.DeleteStatus status =
                    (ProjectMemberController.DeleteStatus)Enum.Parse(typeof(ProjectMemberController.DeleteStatus), exc.ErrorCode().ToString());

                switch (status)
                {
                    case ProjectMemberController.DeleteStatus.CannotDeleteOwner:
                        Messages.ShowWarning(Localization.GetString("WarningCannotDeleteOwner", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.DeleteStatus.NOTMANAGER:
                        Messages.ShowWarning(Localization.GetString("WarningNOTMANAGER", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.DeleteStatus.CANNOTDELETEUSER:
                        Messages.ShowWarning(Localization.GetString("WarningCANNOTDELETEUSER", this.LocalResourceFile));
                        break;

                    case ProjectMemberController.DeleteStatus.USERINTASK:
                        Messages.ShowWarning(Localization.GetString("WarningUSERINTASK", this.LocalResourceFile));
                        break;

                    default:
                        Exceptions.LogException(exc);
                        Messages.ShowError(Localization.GetString("ErrorDeleteMember", this.LocalResourceFile));
                        break;
                }
            }
            catch (Exception exc)
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }

        #endregion "Events"

        #region "Aux Functions"

        /// <summary>
        /// Fills module controls
        /// </summary>
        private void FillControls()
        {
            //fill project members
            RoleController ro = new RoleController();
            var users =
                ro.GetUsersByRoleName(PortalId, MembersRole).OfType<UserInfo>().Select(p => new
                {
                    Id = p.UserID,
                    Name = p.DisplayName + " (" + p.Username + ")"
                });

            drp_members.DataSource = users;
            drp_members.DataValueField = "Id";
            drp_members.DataTextField = "Name";
            drp_members.DataBind();

            drp_members.Items.Insert(0, new ListItem("-", string.Empty));
        }

        /// <summary>
        /// Clears the controls for creating a new project member
        /// </summary>
        private void ClearProjectMemberControl()
        {
            drp_members.ClearSelection();
            chk_isManager.Checked = false;
        }

        /// <summary>
        /// Evaluates if the member parameters are correctly filled
        /// </summary>
        /// <returns>returns true if ok, false otherwise</returns>
        private bool MemberParametersCorrectlyFilled(out int out_userId)
        {
            out_userId = 0;

            if (drp_members.SelectedValue.Equals(string.Empty))
            {
                Messages.ShowWarning(Localization.GetString("ValidationRequiredUserName", this.LocalResourceFile));
                return false;
            }
            else
            {
                out_userId = Convert.ToInt32(drp_members.SelectedValue);
            }

            return true;
        }

        /// <summary>
        /// Fills the language data into the respective controls
        /// </summary>
        private void FillLanguages()
        {
            lt_ProjectMemberEntries.Text = Localization.GetString("lt_ProjectMemberEntries", this.LocalResourceFile);
            chk_isManager.Text = Localization.GetString("chk_isManager", this.LocalResourceFile);
            lt_currentMembers.Text = Localization.GetString("lt_currentMembers", this.LocalResourceFile);
            btn_addMember.Text = Localization.GetString("btn_addMember", this.LocalResourceFile);
        }

        /// <summary>
        /// Gets the project members and binds them into the respective controls
        /// </summary>
        /// <param name="projectId"> the project to collect members from</param>
        private void BindProjectMembers(int projectId, out int out_ownerId)
        {
            //fill existing task comments
            using (UnitOfWork uof = new UnitOfWork(PortalId, ModuleId))
            {
                ProjectMemberController projectMemberController = new ProjectMemberController(uof, projectId);
                FillProjectMembers(uof, projectMemberController);

                //get the project owner
                ProjectController prjController = new ProjectController(uof);
                out_ownerId = prjController.Get(projectId).CreatedByUserID; ;

                pnl_newMember.Visible = IsManager;
            }
        }

        /// <summary>
        /// Fills the list view of project members controller
        /// </summary>
        /// <param name="uof">unit of work</param>
        /// <param name="projectMemberController">Project Member controller</param>
        private void FillProjectMembers(UnitOfWork uof, ProjectMemberController projectMemberController)
        {
            lst_projectMembers.DataSource = projectMemberController.GetAll();
            lst_projectMembers.DataBind();
        }

        #endregion "Aux Functions"
    }
}